package com.richinfo.log;

import com.richinfo.util.Constant;
import com.richinfo.util.DateUtils;
import com.richinfo.util.RespCodeEnum;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;

/**
 * 统一日志工具
 */
public class LogUtils {

	private static Logger db_logger = Logger.getLogger("db");
	private static Logger vip_logger = Logger.getLogger("vip");

	public static final String REQ_JSON_TYPE = "请求报文";
	public static final String REQ_PARAMS_TYPE = "请求参数";

	/**
	 * 请求日志输出
	 * 
	 * @param action
	 *            接口编码
	 * @param method
	 *            执行方法
	 * @param serviceType
	 *            接口名称
	 * @param json
	 *            报文内容
	 */
	public static LogInfo reqLog(String action, String method, String serviceType, String json) {
		LogInfo logInfo = initLogInfo(action, method, serviceType, "请求报文", json);
		setDmcInfo(logInfo);
		db_logger.info(getMessage(logInfo));

		// vip日志控制
		vipLogCtr(logInfo);
		return logInfo;
	}

	/**
	 * 请求日志输出V2
	 * 
	 * @param flag
	 *            日志是否入库
	 * @param action
	 *            接口编码
	 * @param method
	 *            执行方法
	 * @param serviceType
	 *            接口名称
	 * @param json
	 *            报文内容
	 */
	public static LogInfo reqLogV2(boolean flag, String action, String method, String serviceType, String json) {
		LogInfo logInfo = initLogInfo(action, method, serviceType, "请求报文", json);
		setDmcInfo(logInfo);
		if (flag) {
			db_logger.info(getMessage(logInfo));
		}

		// vip日志控制
		vipLogCtr(logInfo);
		return logInfo;
	}

	/**
	 * 请求日志输出V3
	 * 
	 * @param flag
	 *            日志是否入库
	 * @param logType
	 *            请求类型
	 * @param action
	 *            接口编码
	 * @param method
	 *            执行方法
	 * @param serviceType
	 *            接口名称
	 * @param reqInfo
	 *            请求信息
	 */
	public static LogInfo reqLogV3(boolean flag, String logType, String action, String method, String serviceType,
			String reqInfo) {
		LogInfo logInfo = initLogInfo(action, method, serviceType, logType, reqInfo);
		setDmcInfo(logInfo);
		if (flag) {
			db_logger.info(getMessage(logInfo));
		}

		// vip日志控制
		vipLogCtr(logInfo);
		return logInfo;
	}

	/**
	 * 请求日志输出(扩展)
	 * 
	 * @param serviceType
	 *            接口名称
	 * @param json
	 *            报文内容
	 */
	public static LogInfo reqLogWithExStr(String serviceType, String json, LogInfo logInfo) {
		long end = System.currentTimeMillis();
		String totalTime = (float) (end - logInfo.getStart()) / 1000 + "s";
		logInfo.setTotalTime(totalTime);
		logInfo.setServiceType(serviceType);
		logInfo.setJson(json);
		logInfo.setCallTime(DateUtils.getDateTime());
		setDmcInfo(logInfo);
		db_logger.info(getMessage(logInfo));
		return logInfo;
	}

	/**
	 * 请求日志输出(扩展)
	 * 
	 * @param flag
	 *            日志是否入库
	 * @param serviceType
	 *            接口名称
	 * @param json
	 *            报文内容
	 */
	public static LogInfo reqLogWithExStrV2(boolean flag, String serviceType, String json, LogInfo logInfo) {
		long end = System.currentTimeMillis();
		String totalTime = (float) (end - logInfo.getStart()) / 1000 + "s";
		logInfo.setTotalTime(totalTime);
		logInfo.setServiceType(serviceType);
		logInfo.setJson(json);
		logInfo.setCallTime(DateUtils.getDateTime());
		setDmcInfo(logInfo);
		if (flag) {
			db_logger.info(getMessage(logInfo));
		}
		return logInfo;
	}

	/**
	 * 响应日志输出
	 * 
	 * @param json
	 *            报文内容
	 */
	public static LogInfo resLog(String json, LogInfo logInfo) {
		long end = System.currentTimeMillis();
		String totalTime = (float) (end - logInfo.getStart()) / 1000 + "s";
		if (logInfo != null) {
			logInfo.setTotalTime(totalTime);
			logInfo.setOptType("返回报文");
			logInfo.setJson(json);
			logInfo.setCallTime(DateUtils.getDateTime());
			setDmcInfo(logInfo);
		}
		db_logger.info(getMessage(logInfo));
		// HttpServletRequest request = ((ServletRequestAttributes)
		// RequestContextHolder.getRequestAttributes()).getRequest();
		// request.setAttribute("rsp",
		// JSONObject.fromObject(logInfo).toString());

		// vip日志控制
		vipLogCtr(logInfo);
		return logInfo;
	}

	/**
	 * 响应日志输出
	 * 
	 * @param flag
	 *            日志是否入库
	 * @param json
	 *            报文内容
	 */
	public static LogInfo resLogV2(boolean flag, String json, LogInfo logInfo) {
		long end = System.currentTimeMillis();
		String totalTime = (float) (end - logInfo.getStart()) / 1000 + "s";
		if (logInfo != null) {
			logInfo.setTotalTime(totalTime);
			logInfo.setOptType("返回报文");
			logInfo.setJson(json);
			logInfo.setCallTime(DateUtils.getDateTime());
			setDmcInfo(logInfo);
		}

		if (flag) {
			db_logger.info(getMessage(logInfo));
		}

		// vip日志控制
		vipLogCtr(logInfo);
		return logInfo;
	}

	/**
	 * 请求日志输出(分系统输出日志文件)
	 * 
	 * @param method
	 *            执行方法
	 * @param json
	 *            报文内容
	 */
	public static Logger reqLogBySys(String action, String method, String serviceType, String json, Logger logger) {
		JSONObject jsonObject = JSONObject.fromObject(json);
		if (!StringUtils.isEmpty(json)) {
			String appId = jsonObject.getString(Constant.APPID).toString();
			FileAppender appender = new RollingFileAppender();
			PatternLayout layout = new PatternLayout();
			String conversionPattern = "[%d] %p %t %c - %m%n";
			layout.setConversionPattern(conversionPattern);
			appender.setLayout(layout);
			appender.setFile("C:/Users/sooch/Desktop/log/" + appId + ".log");
			appender.setEncoding("UTF-8");
			appender.setAppend(true);
			appender.activateOptions();
			logger.addAppender(appender);
		}
		LogInfo logInfo = initLogInfo(action, method, serviceType, "请求报文", json);
		setDmcInfo(logInfo);
		return logger;
	}

	/**
	 * 将LogInfo解析为制定格式的日志报文
	 * 
	 * @param logInfo
	 * @return
	 */
	public static String getMessage(LogInfo logInfo) {
		StringBuffer logBuffer = new StringBuffer();
		if (logBuffer != null) {
			logBuffer.append(logInfo.getCallTime() + "|");
			logBuffer.append(logInfo.getAction() + "|");
			logBuffer.append(logInfo.getMethod() + "|");
			logBuffer.append(logInfo.getuId() + "|");
			logBuffer.append(logInfo.getServiceType() + "|");
			logBuffer.append(logInfo.getOptType() + "|");
			logBuffer.append(logInfo.getJson());
			if (logInfo.getTotalTime() != null) {
				logBuffer.append("|" + logInfo.getTotalTime());
			}
		}
		return logBuffer.toString();
	}

	public static String getMessage(String... args) {
		String logInfo = "";
		for (String str : args) {
			logInfo += str + "|";
		}
		return logInfo.substring(0, logInfo.length() - 1);
	}

	/**
	 *
	 * @param username
	 *            用户名称
	 * @param args
	 *            参数
	 */
	public static String buildMessage(String username, String... args) {
		StringBuilder strBuilder = new StringBuilder();
		strBuilder.append(username).append("|");
		for (String str : args) {
			strBuilder.append(str).append("|");
		}
		// vip日志控制
		vipLogCtr(username, strBuilder.toString());
		return strBuilder.toString();
	}

	/**
	 * 获取统一日志对象
	 * 
	 * @param action
	 *            接口编码
	 * @param method
	 *            执行方法
	 * @param serviceType
	 *            接口名称
	 * @param optType
	 *            报文名称
	 * @param json
	 *            报文内容
	 * @return 报文对象
	 */
	private static LogInfo initLogInfo(String action, String method, String serviceType, String optType, String json) {
		String uId = "";
		String appId = "";
		String reqId = "";
		String serId = "";

		if (optType.contains("报文")) {
			if (!StringUtils.isEmpty(json)) {
				JSONObject jsonObject = JSONObject.fromObject(json);
				if (jsonObject.containsKey(Constant.APPID)) {
					appId = jsonObject.getString(Constant.APPID).toString();
				} else if (jsonObject.containsKey(Constant.APP_ID)) {
					appId = jsonObject.getString(Constant.APP_ID).toString();
				}
				if (jsonObject.containsKey(Constant.UID)) {
					uId = jsonObject.getString(Constant.UID).toString();
				} else if (jsonObject.containsKey(Constant.USER_ID)) {
					uId = jsonObject.getString(Constant.USER_ID).toString();
				} else if (jsonObject.containsKey(Constant.USERID)) {
					uId = jsonObject.getString(Constant.USERID).toString();
				}
				reqId = !jsonObject.containsKey(Constant.REQID) ? "" : jsonObject.getString(Constant.REQID).toString();
				serId = !jsonObject.containsKey(Constant.SERID) ? "" : jsonObject.getString(Constant.SERID).toString();
			}

		}

		LogInfo logInfo = new LogInfo();
		logInfo.setStart(System.currentTimeMillis());
		logInfo.setAppId(appId);
		logInfo.setuId(uId);
		logInfo.setAction(action);
		logInfo.setMethod(method);
		logInfo.setReqId(reqId);
		logInfo.setSerId(serId);
		logInfo.setJson(json);
		logInfo.setServiceType(serviceType);
		logInfo.setOptType(optType);
		logInfo.setTotalTime("");
		logInfo.setCallTime(DateUtils.getDateTime());
		return logInfo;
	}

	/**
	 * 设置MDC日志信息
	 */
	private static void setDmcInfo(LogInfo logInfo) {

		MDC.put("appId", logInfo.getAppId());
		MDC.put("reqId", logInfo.getReqId());
		MDC.put("serId", logInfo.getSerId());
		MDC.put("uId", logInfo.getuId());
		MDC.put("action", logInfo.getAction());
		MDC.put("method", logInfo.getMethod());
		MDC.put("totalTime", logInfo.getTotalTime());
		MDC.put("serviceType", logInfo.getServiceType());
		MDC.put("optType", logInfo.getOptType());
		MDC.put("totalTime", logInfo.getTotalTime());
		MDC.put("json", logInfo.getJson());
		MDC.put("callTime", logInfo.getCallTime());
	}

	public static boolean isSuccess() {
		return true;
	}

	/**
	 * vip日志输出控制
	 */
	private static void vipLogCtr(LogInfo logInfo) {
		JSONObject json = JSONObject.fromObject(logInfo.getJson());
		String status = json.containsKey("status") ? (String) json.get("status") : "";
		boolean isError = RespCodeEnum.ERROR_1004.getCode().equals(status);
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		List<Map<String, Object>> vipList = (List<Map<String, Object>>) request.getAttribute("vipList");
		if (vipList != null) {
			for (Map<String, Object> vip : vipList) {
				if (logInfo.getAction().equals(Constant.ACTION_LOGIN)) {
					if (logInfo.getuId().equals(vip.get("portal_no"))) {
						if (isError) {
							vip_logger.error(getMessage(logInfo));
						} else {
							vip_logger.info(getMessage(logInfo));
						}

					}
				} else {
					if (logInfo.getuId().equals(vip.get("uid"))) {
						if (isError) {
							vip_logger.error(getMessage(logInfo));
						} else {
							vip_logger.info(getMessage(logInfo));
						}
					}
				}

			}

		}
	}

	/**
	 * vip日志输出控制
	 */
	private static void vipLogCtr(String username, String message) {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		List<Map<String, Object>> vipList = (List<Map<String, Object>>) request.getAttribute("vipList");
		if (vipList != null) {
			for (Map<String, Object> vip : vipList) {
				if (username.equals(vip.get("portal_no"))) {
					vip_logger.info(message);
				}
			}
		}
	}
}
